16. Interpreter


Posted by WayneCheng on 2021-01-23

關於 Interpreter 本篇將討論以下幾個問題

1. 關於 Interpreter

2. UML

3. 將 UML 轉為程式碼


測試環境:

OS:Windows 10
IDE:Visual Studio 2019


1. 關於 Interpreter

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

by Gang of Four

  • 給定一種語言,直譯器為這語言的文法定義一種描述,使用描述來解釋語言中的句子

Interpreter(直譯器)屬於行為型(Behavioral Patterns),當遇到大量相同問題,且有特定的處理方式時,可以藉由 Interpreter 來將問題的處理方式集中管理,且有新處理方式時,只需要將新處理方式加入 Interpreter 即可。

優點:

  • 符合 單一職責原則(Single Responsibility Principle)
  • 符合 開閉原則(Open Closed Principle)

缺點:

  • 複雜的情境會產生大量的 class 造成整體程式複雜度提升
  • 遞迴方式呼叫再複雜的情境下可能會有效能的問題

2. UML

Class 間關聯:

  • Client 關聯 Context & AbstractExpression
  • TerminalExpression & NonterminalExpression 繼承 AbstractExpression
  • NonterminalExpression 可包含 AbstractExpression

Class:

  • Client:呼叫端
  • AbstractExpression:直譯的抽象類別或介面
  • TerminalExpression:直譯邏輯實作,已無接續項目,不再遞迴
  • NonterminalExpression:直譯邏輯實作,有接續項目
  • Context:由直譯器來處理的內容

3. 將 UML 轉為程式碼

由直譯器來處理的內容

/// <summary>
/// 由直譯器來處理的內容
/// </summary>
public class Context
{
}

直譯的抽象類別或介面

/// <summary>
/// 直譯的抽象類別或介面
/// </summary>
public abstract class AbstractExpression
{
    public abstract void Interpret(Context context);
}

直譯邏輯實作,已無接續項目,不再遞迴

/// <summary>
/// 直譯邏輯實作,已無接續項目,不再遞迴
/// </summary>
public class TerminalExpression : AbstractExpression
{
    public override void Interpret(Context context)
    {
        Console.WriteLine("Called Terminal.Interpret()");
    }
}

直譯邏輯實作,有接續項目

/// <summary>
/// 直譯邏輯實作,有接續項目
/// </summary>
public class NonterminalExpression : AbstractExpression
{
    public override void Interpret(Context context)
    {
        Console.WriteLine("Called Nonterminal.Interpret()");
    }
}

呼叫直譯器並傳入欲處理內容

static void Main(string[] args)
{
    Default.Context context = new Default.Context();

    ArrayList list = new ArrayList();

    list.Add(new Default.TerminalExpression());
    list.Add(new Default.NonterminalExpression());
    list.Add(new Default.TerminalExpression());
    list.Add(new Default.TerminalExpression());

    foreach (Default.AbstractExpression exp in list)
    {
        exp.Interpret(context);
    }

    Console.ReadLine();
}

執行結果

Called Terminal.Interpret()
Called Nonterminal.Interpret()
Called Terminal.Interpret()
Called Terminal.Interpret()

完整程式碼

GitHub:Behavioral_03_Interpreter


總結

Interpreter 網路上看到例子像是 Regular Expression轉換、數字轉換之類的,都滿難想像如何套用至我們的日常開發中,會這樣覺得並不奇怪,因為 Interpreter 本來就屬於較少機會使用到的 Pattern,在複雜情境中還有效能問題,故本篇沒有附上情境範例。

不過基本概念還是可以了解一下,真的遇到要使用時再詳細了解即可。


參考資料

  1. Design Patterns
  2. 大話設計模式
  3. dofactory

新手上路,若有錯誤還請告知,謝謝


#designpattern #CSharp







Related Posts

command line,那個電影世界裡駭客電腦上的黑色小視窗

command line,那個電影世界裡駭客電腦上的黑色小視窗

COSCUP 2020 貼紙蒐集者

COSCUP 2020 貼紙蒐集者

部署 (1) —— 建立 AWS EC2 主機及 SSH 連線

部署 (1) —— 建立 AWS EC2 主機及 SSH 連線


Comments